package com.handu.luna.mall.controller.support;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.handu.luna.mall.controller.BaseController;
import com.handu.luna.mall.controller.SessionUser;
import com.handu.luna.core.domain.support.EnumAwareConvertUtilsBean;
import com.handu.luna.core.domain.user.User;

public class UserInterceptor extends HandlerInterceptorAdapter {
	protected Log logger = LogFactory.getLog(this.getClass());

	public static final String SESSION_ID_FLAG = "luna_session_id";
	public static final String LOGIN_URL = "/login/index";
	public static final String LOGIN_VALID_URL = "/login/login";
	public static final String HOME_URL = "/login/login";
	public static final int SESSION_TIMEOUT = -1;
	public static final int SESSION_AUTO_TIMEOUT = 60 * 60 * 24 * 14;
	@Autowired
	private SessionUser sessionService;

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		BeanUtilsBean.setInstance(new BeanUtilsBean(
				new EnumAwareConvertUtilsBean()));
		if (handler instanceof HandlerMethod || handler instanceof BaseController) {
			String sessionId = getSessionId(request, response);
			SessionUser session = sessionService.getOrCreateSession(sessionId);
			if (sessionId == null) {
				setCookie(response, sessionService.getOrCreateSession(null).getId());
				if (handler instanceof HandlerMethod) {
					HandlerMethod method = (HandlerMethod) handler;
					setValue(method.getBean(), session, new User());
				}
				return true;
			}
			User currentUser = session.getUser();
			if (currentUser == null) {
				if (handler instanceof HandlerMethod) {
					HandlerMethod method = (HandlerMethod) handler;
					setValue(method.getBean(), session, new User());
				}
				return true;
			} else {
				if (handler instanceof HandlerMethod) {
					HandlerMethod method = (HandlerMethod) handler;
					Object obj = method.getBean();
					setValue(obj, session, currentUser);
				} else if (handler instanceof BaseController) {
					setValue(handler, session, currentUser);
				}
			}

		}
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		super.postHandle(request, response, handler, modelAndView);
	}

	private void setValue(Object _controller, SessionUser session,
			User currentUser) {
		BaseController controller = (BaseController) _controller;
		controller.setSession(session);
		controller.setCurrentUser(currentUser);
	}

	/**
	 * 返回session id，如果第一次访问或异常访问则返回null
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @return 返回session id，如果第一次访问或异常访问则返回null
	 */
	private String getSessionId(HttpServletRequest request,
			HttpServletResponse response) {
		String sessionId = null;
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals(SESSION_ID_FLAG)) {
					sessionId = cookie.getValue();
				}
			}
		}
		return sessionId;
	}

	/**
	 * 设置用户会话cookie TODO:
	 * 这里存在一个问题，用户可以自行修改cookie过期时间。不过由于cookie机制的安全性，一般认为不是大问题。作为未来改进点。
	 * 
	 * @param response
	 * @param sessionId
	 */
	private void setCookie(HttpServletResponse response, String sessionId) {
		Cookie cookie = new Cookie(SESSION_ID_FLAG, sessionId);
		cookie.setPath("/");
		
		cookie.setMaxAge(SESSION_TIMEOUT);
		
		response.addCookie(cookie);
	}
}
